import QtQuick
import QtQuick3D
import QtQuick3D.Physics

import QtQuickRO
import "../EventBus"
import "./CharacterPrivate"
/*
    角色是一种能够受玩家操控类人型的实体，它的内部有一个CharacterController来控制角色的移动。
    想要获取角色位置可以依靠characterPosition
    服务端和客户端角色位置实时同步。当服务端和客户端角色位置有差异时会有机制来调整
*/
Pawn{
    id:root
    
    property alias capsuleShape:capsuleShape
    property alias capsuleHeight:capsuleShape.height
    property alias capsuleDiameter:capsuleShape.diameter

    property alias receiveContactReports : characterController.receiveContactReports
    property alias receiveTriggerReports : characterController.receiveTriggerReports
    property alias sendContactReports : characterController.sendContactReports
    property alias sendTriggerReports : characterController.sendTriggerReports
    
    property alias characterController:characterController
    
    property alias midAirControl:characterController.midAirControl
    
    //角色的移动方向，这是一个同步变量.
    //要想控制角色移动必须在服务端设置这个值来实现
    property alias movement:shared.movement
    
    //玩家的初始位置
    property alias characterPosition:characterController.position
    //玩家的初始旋转角度
    property alias characterRotation:characterController.rotation
    
    //角色的网络误差最大值，超过这个值后会直接将角色拉到目标位置
    property vector3d tolerance:Qt.vector3d(50, 50, 50)

    CharacterController{
        id:characterController
        property alias capsuleDiameter:capsuleShape.diameter
        property alias capsuleHeight:capsuleShape.height
        property alias capsuleShape:capsuleShape
        
        movement: locationControl.outputMovement
        gravity:Qt.vector3d(0,-981,0)
        
        ROSharedObject{
            id:shared
            
            updater:ROHelper.framed//使用udp帧同步
            property vector3d movement
            
            //将服务端角色位置同步给所有客户端
            property vector3d position:characterController.position
        }
        
        Node{
            id:locationControl
            
            //角色移动的阻力，由客户端和服务端位置的差异计算得出
            property vector3d resistor:calculateResistances()
            
            function calculateResistance(cur,real){
                let dis = cur - real
                return -dis
            }
            
            function calculateResistances(){
                var ret = Qt.vector3d(0,0,0)
                let target = characterController
                
                ret.x = calculateResistance(target.position.x,shared.position.x)
                ret.y = calculateResistance(target.position.y,shared.position.y)
                ret.z = calculateResistance(target.position.z,shared.position.z)
                return ret
            }
            property vector3d outputMovement: getOutputMovement()
            function getOutputMovement(){
                let ret = Qt.vector3d(0,0,0)
                
                ret.x = shared.movement.x + resistor.x
                ret.y = shared.movement.y + resistor.y
                ret.z = shared.movement.z + resistor.z
                
                return ret
            }
            
            Timer{
                running: shared.role === RORPC.Client
                repeat: true
                interval: 250
                
                
                function calculateDistance(cur,real,tolerance){
                    let dis = cur - real
                    if(Math.abs(dis) < tolerance)
                    {
                        return cur
                    }
                    
                    return real
                }
                
                onTriggered: {
                    var move = Qt.vector3d(0,0,0)
                    let target = characterController
                    move.x = calculateDistance(target.position.x,shared.position.x,tolerance.x)
                    move.y = calculateDistance(target.position.y,shared.position.y,tolerance.y)
                    move.z = calculateDistance(target.position.z,shared.position.z,tolerance.z)
                    
                    if(move.x !== target.position.x || move.y !== target.position.y || move.z !== target.position.z)
                    {
                        target.teleport(move)
                    }
                }
            }
        }
        
        collisionShapes: CapsuleShape {
            id: capsuleShape
            diameter: 100
            height:100
        }

    }

    Node {
        id: __materialLibrary__

        PrincipledMaterial {
            id: principledMaterial
            objectName: "principledMaterial"
        }
    }
}


